/* -----------------------------------------------------------------------------
 * PROJECT    : lwf_handlers
 * FILE       : AlgebraProcessHandler.java
 *
 * HISTORY:
 * Date          Author                        Description
 * ----------------------------------------------------------------------------- 
 * Feb 13, 2011  mycodetalks			       Created
 */
package net.lwf.handler.math.algebra;

import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import java.util.StringTokenizer;

import lwf.handler.entities.math.Sum;
import lwf.handler.entities.math.SumUtil;
import net.lwf.common.constant.ICommonConstant;
import net.lwf.entity.QuestionInfo;
import net.lwf.handler.constant.IHandlerConstant;
import net.lwf.handler.math.ArithGebraProcessHandler;
import net.lwf.number.util.NumberFormatter;
import net.lwf.number.util.RandomNumberGenerator;
import net.lwf.pdf.util.FontUtil;
import net.lwf.string.util.StringManipulator;

import com.itextpdf.text.Element;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;

/**
 * Class description goes here
 */
public class AlgebraProcessHandler extends ArithGebraProcessHandler {
	
	private static final String PDF_DATA_FILE = "algebra_pdf_data";

	public AlgebraProcessHandler(String grade, String operation) {
		//super(grade, operation);
		super(grade, operation, PDF_DATA_FILE);
	}
	
	public AlgebraProcessHandler(String grade, String operation, boolean needDecimals) {
		super(grade, operation, PDF_DATA_FILE, needDecimals);
	}
	
	//-----------------------------------------------------------------------------------
	// Abstract methods
	//-----------------------------------------------------------------------------------
	@Override
/*	public QuestionInfo generateSingle() {
		Sum sum = null;
		if(getOperation().equals(IHandlerConstant.DIVISION)) {
			sum = getAlgebraicSumForDevide();
		}
		else {
			sum = this.generateSum();
		}
		QuestionInfo qinfo = new QuestionInfo();
		
		List<Double> qdata = sum.getData();
		int questionPosition = RandomNumberGenerator.generate(1, qdata.size());
		List<String> formatteddata = new ArrayList<String>();
		int nCounter = 1;
		
		for(Double data: qdata) {
			String formatted;
			if(getOperation().equals(IHandlerConstant.DIVISION)) {
				formatted = NumberFormatter.format(data, getDecimaldigits(), false);
			}
			else {
				formatted = NumberFormatter.format(data, getDecimaldigits(), true);	
			}
			
			if(nCounter == questionPosition) {
				formatteddata.add("?");
				//Swap the answer
				String formattedAnswer;
				if(getOperation().equals(IHandlerConstant.DIVISION)) {
					formattedAnswer = getFormattedAnswer(sum.getAnswer());
				}
				else {
					formattedAnswer = NumberFormatter.format((Double) sum.getAnswer(), getDecimaldigits(), true);	
				} 
				qinfo.setPlaceHolder(formattedAnswer);
				//Reset value
				qinfo.setAnswer(formatted);
				
			}
			else {
				formatteddata.add(formatted);
			}
			nCounter++;
		}

		qinfo.setQuestionObject(formatteddata);

		return qinfo;
	}*/
	
	protected QuestionInfo generateSingle(boolean formultiple) {
		Sum sum = null;
		if(getOperation().equals(IHandlerConstant.DIVISION)) {
			sum = getAlgebraicSumForDevide();
		}
		else {
			sum = this.generateSum();
		}
		QuestionInfo qinfo = null;
		
		List<Double> qdata = sum.getData();
		int questionPosition = RandomNumberGenerator.generate(1, qdata.size());
		List<String> formatteddata = new ArrayList<String>();
		int nCounter = 1;
		
		for(Double data: qdata) {
			String formatted;
			if(getOperation().equals(IHandlerConstant.DIVISION)) {
				formatted = NumberFormatter.format(data, getDecimaldigits(), false);
			}
			else {
				formatted = NumberFormatter.format(data, getDecimaldigits(), true);	
			}
			
			if(nCounter == questionPosition) {
				formatteddata.add("?");
				//Swap the answer
				String formattedAnswer;
				if(getOperation().equals(IHandlerConstant.DIVISION)) {
					formattedAnswer = getFormattedAnswer(sum.getAnswer());
				}
				else {
					formattedAnswer = NumberFormatter.format((Double) sum.getAnswer(), getDecimaldigits(), true);	
				} 
				
				if(!formultiple) {
					
					if(!getOperation().equalsIgnoreCase(IHandlerConstant.DIVISION)) {
						qinfo = new QuestionInfo();
					}
					else {
						qinfo = new QuestionInfo(generateAnswerChoices(formatted));
					}
					qinfo.setDecimalDigits(getDecimaldigits());
				}
				else {
					qinfo = new QuestionInfo();
				}
				
				qinfo.setPlaceHolder(formattedAnswer);
				//Reset value
				qinfo.setAnswer(formatted);
				
			}
			else {
				formatteddata.add(formatted);
			}
			nCounter++;
		}

		qinfo.setQuestionObject(formatteddata);

		return qinfo;
	}
	
	/**
	 * @return Returns the questiondesc.
	 */
	public String getQuestionDesc() {
		StringBuffer sbQ = new StringBuffer();
		if(this.getOperation().equals(IHandlerConstant.ADDITION)) {
			List<String> data = this.getAdddata();
			for(int i=0; i<data.size(); i++) {
				String qData = (String) data.get(i);
				sbQ.append(NumberFormatter.format(qData, getDecimaldigits()));
				if(i+1 < data.size()) {
					sbQ.append(" ");
					sbQ.append(this.getOperationsign());
					sbQ.append(" ");
				}
				else {
					sbQ.append(" = ");
				}
			}
		}
		else {
			sbQ.append(NumberFormatter.format(this.getData1(), getDecimaldigits()));
			sbQ.append(" ");
			sbQ.append(this.getOperationsign());
			sbQ.append(" ");	
			sbQ.append(NumberFormatter.format(this.getData2(), getDecimaldigits()));
			sbQ.append(" ");
			sbQ.append(" = ");
		}
		return sbQ.toString();
	}
	
	public boolean matchAnswer(String useranswer, QuestionInfo qinfo) {
		//remove "," if any
		if(useranswer != null && useranswer.trim().length() != 0) {
			useranswer = StringManipulator.replace(useranswer, ICommonConstant.COMMA, "");
		}
		//ArithmaticQuestion aq = (ArithmaticQuestion) attemptedQuestion;
		String formattedAnswer = NumberFormatter.format(useranswer.trim(), qinfo.getDecimalDigits());
		
		if(qinfo.getAnswer().equalsIgnoreCase(formattedAnswer)) {
			return true;
		}
		return false;
	}
	//-----------------------------------------------------------------------------------
	// Other public methods
	//-----------------------------------------------------------------------------------	
	
	public QuestionInfo generateQuestion() {
		init();
		QuestionInfo qinfo = generateSingle();
		this.generateQuestionString(qinfo);
		//ArithmaticQuestion question = new ArithmaticQuestion();
		qinfo.setAnswer(qinfo.getAnswer());
		qinfo.setOperation(getOperation());
		qinfo.setDecimalDigits(getDecimaldigits());
		qinfo.setQuestion(qinfo.getQuestion());	//Set Question String
		qinfo.setHtmlQuestion(generateHtmlQuestionString(qinfo));	//Set Html Question String
		
		return qinfo;
	}
	
	
	@SuppressWarnings("unchecked")
	public Element processCellData(QuestionInfo question) {
		//AlgebraQuestionInfo info = (AlgebraQuestionInfo) question;

		List<String> qdata = (List<String>) question.getQuestionObject();
		//int columns = qdata.size() + (qdata.size() - 1) + 2;
		PdfPTable table = new PdfPTable(1);
        table.setSpacingBefore(20);

        PdfPCell cell;
        cell = new PdfPCell(new Phrase("# " + question.getQuestionNumber(), FontUtil.getQuestionNumberFont()));
        cell.setBorder(0);
        
        //cell.setColspan(columns); 
        table.addCell(cell);
        
        int nCounter = 1;
        String questionString = "";
		for(int i=qdata.size(); i>0; i--) {
			questionString += qdata.get(i-1);
			if (nCounter < qdata.size()) {
				questionString += ICommonConstant.EMPTY_SPACE + SumUtil.getOperationSign(getOperation()) + ICommonConstant.EMPTY_SPACE;
			}
			nCounter++;
		}
		questionString += ICommonConstant.EMPTY_SPACE + ICommonConstant.EQUAL_TO;
		questionString += ICommonConstant.EMPTY_SPACE + question.getPlaceHolder().toString();
		cell = new PdfPCell(new Phrase(questionString, FontUtil.getDisplayFont()));
		cell.setNoWrap(true);
		cell.setBorder(0);
		table.addCell(cell);

        table.completeRow();

        
		return table;
	}
	
	/**
	 * @see net.lwf.handler.ProcessHandler#getPdfInstructionalText()
	 */
	public String getPdfInstructionalText() {
		String text = "Solve the following ";
		if(getOperation().equalsIgnoreCase(IHandlerConstant.ADDITION)) {
			text += IHandlerConstant.ADDITION;
		}
		else if(getOperation().equalsIgnoreCase(IHandlerConstant.SUBTRACTION)) {
			text += IHandlerConstant.SUBTRACTION;
		}
		else if(getOperation().equalsIgnoreCase(IHandlerConstant.MULTIPLICATION)) {
			text += IHandlerConstant.MULTIPLICATION;
		}
		else  {
			text += IHandlerConstant.DIVISION;
		}
		return text + " algebraic expression.";
	}
	
	public String[] getPdfData(String key) {
		String[] pdfdata = new String[2];
		try {
			ResourceBundle bundle = ResourceBundle.getBundle(PDF_DATA_FILE);
			String data = bundle.getString(key);
			StringTokenizer stk = new StringTokenizer(data, ICommonConstant.PIPE);
			pdfdata[0] = stk.nextToken();
			pdfdata[1] = stk.nextToken();			
		}
		catch(Exception ex) {
			if(getOperation().equalsIgnoreCase(IHandlerConstant.DIVISION)) {
				pdfdata[0] = "13";
			}
			else {
				pdfdata[0] = "14";
			}
			
			pdfdata[1] = "1";
		}

		return pdfdata;
	}

	//-----------------------------------------------------------------------------------
	// Private methods
	//-----------------------------------------------------------------------------------
	
	@SuppressWarnings("unchecked")
	private void generateQuestionString(QuestionInfo qinfo) {
		StringBuffer sbQ = new StringBuffer();
		List<String> formattedData = (List<String>) qinfo.getQuestionObject();

		int nCounter = 1;

		//for (String data : formattedData) {
		for(int i=formattedData.size(); i>0; i--) {
			sbQ.append(formattedData.get(i-1));

			if (nCounter < formattedData.size()) {
				sbQ.append(" ");
				sbQ.append(SumUtil.getOperationSign(getOperation()));
				sbQ.append(" ");
			}
			nCounter++;
		}
		sbQ.append(" = ");
		sbQ.append(qinfo.getPlaceHolder().toString());
		qinfo.setQuestion(sbQ.toString());
	}
	
	@SuppressWarnings("unchecked")
	private String generateHtmlQuestionString(QuestionInfo qinfo) {
		List<String> formattedData = (List<String>) qinfo.getQuestionObject();
		StringBuffer sbHtml = new StringBuffer("<table border=\"0\" align=\"center\" >");
		sbHtml.append("<tr>");
		int nCounter = 1;
		//for (String data : formattedData) {
		for(int i=formattedData.size(); i>0; i--) {
			String data = formattedData.get(i-1);
			if(data.equals(ICommonConstant.QUESTION)) {
				sbHtml.append("<td class=\"question\" >");
				sbHtml.append(ICommonConstant.EMPTY_SPACE + ICommonConstant.QUESTION + ICommonConstant.EMPTY_SPACE);
			}
			else {
				sbHtml.append("<td class=\"datacenter\" >");
				sbHtml.append(data);
			}
			if (nCounter < formattedData.size()) {
				sbHtml.append("<td>");
				sbHtml.append(SumUtil.getOperationImageHtml(getOperation()));
				sbHtml.append("</td>");
			}
			nCounter++;
		}
		sbHtml.append("<td class=\"data\" >");
		sbHtml.append(ICommonConstant.EMPTY_SPACE + ICommonConstant.EQUAL_TO + ICommonConstant.EMPTY_SPACE);
		sbHtml.append("</td>");
		sbHtml.append("<td class=\"data\" >");
		sbHtml.append(qinfo.getPlaceHolder().toString());
		sbHtml.append("</td>");
		sbHtml.append("</tr>");
		sbHtml.append("</table>");
		
		return sbHtml.toString();
	}


} //AlgebraProcessHandler



